

#include "msghandler.h"
#include "package.h"

int MsgHandler :: mMsgSeq = 0;

MsgHandler :: MsgHandler( ServiceManager * manager )
{
	memset( &mSid, 0, sizeof( mSid ) );
	mServiceManager = manager;
}

MsgHandler :: ~MsgHandler()
{
	
}
void MsgHandler :: post( SP_Response * response, const char * buffer,size_t size, UserList* toUsers)
{
	if( toUsers->getCount() > 0 ) {
		SP_Message * msg = new SP_Message();
		msg->setCompletionKey( ++mMsgSeq );
		msg->getMsg()->append( buffer ,size);
		toUsers->copy(msg->getToList());
		response->addMessage( msg );
	}
}
void MsgHandler :: post( SP_Response * response, const char * buffer,size_t size, SP_Sid_t toSid)
{
	SP_Message * msg = new SP_Message();
	msg->setCompletionKey( ++mMsgSeq );
	msg->getMsg()->append( buffer ,size);
	msg->getToList()->add(toSid);
	response->addMessage( msg );
}
void MsgHandler :: broadcast( SP_Response * response, const char * buffer,size_t size, SP_Sid_t * ignoreSid )
{
	
}
void MsgHandler :: broadcast( SP_Response * response, const string& msg, SP_Sid_t * ignoreSid )
{
	broadcast(response,msg.c_str(),msg.size(),ignoreSid);
}
int MsgHandler :: start( SP_Request * request, SP_Response * response )
{
	request->setMsgDecoder( new MsgDecoder() );
	mSid = response->getFromSid();

	mServiceManager->getUserList()->add( mSid );
	return 0;
}
bool messageTypeMatch(const std::string& type1,const std::string& type2)
{
	return 0==strcmp(type1.c_str(),type2.c_str());
}
void MsgHandler :: process(Package* package, SP_Response * response)
{
	std::string msgtype=package->getClassType();
	unsigned char packagetype=package->getPackageType();
	if(messageTypeMatch(msgtype,MsgExpress::RegService::default_instance().GetTypeName() ))
	{
		MsgExpress::RegService* service=(MsgExpress::RegService*)package->getMessage().get();
		int total=service->classname_size();
		vector<const std::string> vecClass;
		for(int i=0;i<total;i++)
		{
			std::string classname=service->classname(i);
			if(mServiceList.count(classname)==0)
			{
				mServiceList.insert(classname);
			    vecClass.push_back(service->classname(i));
			}
		}
		mServiceManager->regService(vecClass,mSid);

		MsgExpress::Response resp;
		resp.set_retcode(0);
		resp.set_msg("Reg service OK!");
		std::string msg;
		MessageUtil::serializePackageToString(resp,MsgType::Response,package->getSerialNum(),0,&msg);
		response->getReply()->getMsg()->append(msg.c_str(),msg.size());
		response->getReply()->setCompletionKey( ++mMsgSeq );
		printf("Reg service:%s\r\n",service->ShortDebugString().c_str());
	}
	else if(messageTypeMatch(msgtype,MsgExpress::Subscribe::default_instance().GetTypeName() ))
	{
		MsgExpress::Subscribe* request=(MsgExpress::Subscribe*)package->getMessage().get();
		int total=request->classname_size();
		vector<const std::string> vecClass;
		for(int i=0;i<total;i++)
		{
			std::string classname=request->classname(i);
			if(mSubscribeList.count(classname)==0)
			{
				mSubscribeList.insert(classname);
			    vecClass.push_back(request->classname(i));
			}
		}
		mServiceManager->subscribe(vecClass,mSid);

		MsgExpress::Response resp;
		resp.set_retcode(0);
		resp.set_msg("Sunscribe service OK!");
		std::string msg;
		MessageUtil::serializePackageToString(resp,MsgType::Response,package->getSerialNum(),0,&msg);
		response->getReply()->getMsg()->append(msg.c_str(),msg.size());
		response->getReply()->setCompletionKey( ++mMsgSeq );
		printf("Sunscribe service:%s\r\n",request->ShortDebugString().c_str());
	}
	else if(packagetype==MsgType::Publish)
	{
		UserList* toUsers=mServiceManager->getServiceSubscriber(msgtype);
		if(toUsers && toUsers->getCount()>0)
		    post(response,package->getContent(),package->getSize(),toUsers);
		printf("Publish:%s\r\n",msgtype.c_str());
	}
	else if(packagetype==MsgType::Request)
	{
		UserList* providers=mServiceManager->getServiceProvider(msgtype);
		if(providers && providers->getCount()>0)
		{
			package->setSrcAddr(mSid.mKey);
		    post(response,package->getContent(),package->getSize(),providers->getRandUser());
		    printf("Request:%s\r\n",msgtype.c_str());
		}
		else //send common response msg
		{
		}
	}
	else if(packagetype==MsgType::Response)
	{
		unsigned short dst=package->getDstAddr();
		SP_Sid_t sid;
		sid.mKey=dst;
		sid.mSeq=0;
		post(response,package->getContent(),package->getSize(),sid);
		printf("Response:%s\r\n",msgtype.c_str());
	}
}

int MsgHandler :: handle( SP_Request * request, SP_Response * response )
{
	MsgDecoder * decoder = (MsgDecoder*)request->getMsgDecoder();
	SP_CircleQueue * msgQueue = decoder->getQueue();

	char buffer[ 256 ] = { 0 };
	int ret = 0;

	for( ; NULL != msgQueue->top(); ) {
		void* p=msgQueue->pop();
		Package * package = (Package*)p;
		if(package!=NULL){
		    process(package,response);
		}
		delete p;
	}

	return ret;
}

void MsgHandler :: error( SP_Response * response )
{
	char buffer[ 64 ] = { 0 };
	snprintf( buffer, sizeof( buffer ), "SYS : %d error offline\r\n", mSid.mKey );

	broadcast( response, buffer, strlen(buffer),&mSid );
}

void MsgHandler :: timeout( SP_Response * response )
{
	char buffer[ 64 ] = { 0 };
	snprintf( buffer, sizeof( buffer ), "SYS : %d timeout offline\r\n", mSid.mKey );

	broadcast( response, buffer,strlen(buffer), &mSid );
}

void MsgHandler :: close()
{
	mServiceManager->getUserList()->remove( mSid );
	if(mServiceList.size()>0)
	    mServiceManager->unregService(mServiceList,mSid);
	if(mSubscribeList.size()>0)
		mServiceManager->unSubscribe(mSubscribeList,mSid);
}


void MsgCompletionHandler :: completionMessage( SP_Message * msg )
{
#if 0
	printf( "message completed { completion key : %d }\n", msg->getCompletionKey() );

	printf( "\tsuccess {" );
	for( int i = 0; i < msg->getSuccess()->getCount(); i++ ) {
		printf( " %d", msg->getSuccess()->get( i ).mKey );
	}
	printf( "}\n" );

	printf( "\tfailure {" );
	for( int i = 0; i < msg->getFailure()->getCount(); i++ ) {
		printf( " %d", msg->getFailure()->get( i ).mKey );
	}
	printf( "}\n" );
#endif

	delete msg;
}